home *** CD-ROM | disk | FTP | other *** search
- /*- PATHSUB - Substitute strings in environment variables (default: PATH)
-
- Usage: PATHSUB [/var] pat sub
-
- PATHSUB will substitute the 1st occurrance of 'pat' in the environment
- variable 'var' with the replacement string 'sub'. Both 'pat' and 'sub'
- are required. The default environment variable is "PATH".
-
- If 'var' is specified, it is converted to uppercase. Both 'pat' and
- 'sub' are case sensitive.
-
- There are two special values for the parameter 'pat'. If 'pat' is "^"
- then 'sub' will be placed at the head of the environment variable (after
- the '=' seperating the variable name from the value). If 'pat' is "$"
- then 'sub' will be placed at the end of the environment. Note that
- this is not full regular expression matching. The pattern "^C:\BIN"
- will NOT attempt to find "C:\BIN" at the head of the path, but will
- search for "^C:\BIN" anywhere in the path.
-
- If you wish to delete something from the path, overspecify the pattern
- and make the replacement match the extra e.g.:
-
- PATHSUB ;C:\UTILS; ;
-
- Exit codes:
- 4 - Program could not run, not enough parameters
- 3 - Program could not locate environment variable
- 2 - Pattern not found in environment variable
- 1 - Program could not update environment, substitution too big
- 0 - Success
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <process.h>
- #include <memory.h>
- #include <ctype.h>
- #include <dos.h>
- #include <string.h>
-
- #ifndef TRUE
- #define TRUE 1
- #endif
-
- #ifndef FALSE
- #define FALSE 0
- #endif
-
- #ifndef NULL
- #define NULL 0
- #endif
-
- #define Lastchar(string) string[strlen(string)-1]
-
- #define DEBUG TRUE
- #define VERBOSE TRUE
-
- #define ENV_OFF 0x2C /* environment segment */
- #define PPSP_OFF 0x16 /* parent PSP */
- /* PSP of copy of COMMAND.COM that invoked current process */
- #define RPSP_OFF 0x10
-
- /* Maximum memory block we will try to deal with is 255 Paragraphs long */
- #define MAXLEN 0xFF0
-
- extern unsigned _psp; /* from MSC: PSP segment for this task */
-
- unsigned _rpsp; /* "root" PSP segment */
- unsigned _cpsp; /* current PSP segment */
- unsigned _env_seg; /* environment segment */
- unsigned _ctrl_seg; /* memory control block segment */
- unsigned _mem_seg; /* memory block segment */
-
- struct _ctrl_block
- {
- char type; /* 'M' more memory follows, 'Z' zero more blocks */
- unsigned owner; /* PSP of task which owns this memory */
- unsigned length; /* # of segments in this block of memory */
- } ctrl_block;
-
- unsigned char mem_block[MAXLEN];
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- unsigned _showds();
-
- static char cmdpath[256];
- static char path[256];
- static char target[100] = { "PATH=" };
- char *comspec,*pos;
- int i, done;
- int ppos, off;
- unsigned ds;
- int firstarg;
-
- firstarg=1;
-
- /* if alternate environment var specified */
- if (argv[firstarg][0] == '/')
- {
- strcpy(target, argv[firstarg++]+1); /* copy from arg (after '/') */
- strcat(target, "="); /* append an '=' */
- strupr(target); /* convert to uppercase */
- }
-
- if (argc < firstarg+2)
- {
- fprintf(stderr, "\nPATHSUB: Usage - PATHSUB [/var] pat sub");
- exit(4);
- }
-
- ds = _showds(); /* get our data segment */
- _rpsp = _psp; /* start w/ our own PSP segment */
- _cpsp = _rpsp ^ 0xFFFF; /* Dummy value to start with */
-
- while (_cpsp != _rpsp) /* while haven't found PSP of 1st COMMAND */
- {
- _cpsp = _rpsp; /* up another layer */
- /* get "root" PSP segment */
- movedata(_cpsp, RPSP_OFF, ds, (unsigned)&_rpsp, 2);
- }
-
- /* get the memory control block from the root PSP */
- _mem_seg = _cpsp; /* start with the PSP segment */
- _ctrl_seg = _cpsp - 1; /* and back up by one segment */
-
- /* copy it to where we can use it */
- movedata(_ctrl_seg, 0, ds, (unsigned)&ctrl_block, sizeof(ctrl_block));
-
- done = FALSE;
- ppos = -1;
- while (!done)
- {
- /* find next control block */
- _ctrl_seg = _mem_seg + ctrl_block.length;
- /* & next block of memory */
- _mem_seg = _ctrl_seg + 1;
- /* load control block */
- movedata(_ctrl_seg, 0, ds, (unsigned)&ctrl_block.type, 5);
-
- done = (ctrl_block.type != 'M');
- if(!done)
- /* examine mem block, if not too big */
- if(ctrl_block.length < MAXLEN)
- {
- /* Load the block */
- movedata(_mem_seg, 0, ds, (unsigned)mem_block,
- ctrl_block.length*16);
-
- /* find the first occurance of our pattern in the block */
- /* if it does not appear, result will be -1 */
-
- /* search the block */
- for(ppos = off = 0; !done && off != -1; ppos++)
- {
- /* if found */
- if( (off = memsrch(&mem_block[ppos], target,
- (ctrl_block.length*16)-off )) != -1)
- {
- ppos+=off;
- /* and if valid */
- if(ppos == 0 || mem_block[ppos-1] == NULL)
- {
- done = TRUE; /* set to break main loop */
- break; /* get out of for loop */
- }
- }
- }
- } /* end: look through this memory block */
- } /* end: look through all memory blocks */
-
- if((ppos == -1) || (ctrl_block.type != 'M'))
- {
- Lastchar(target);
- fprintf(stderr,
- "\nPATHSUB: Could not locate environment variable [%s].",
- target);
- exit(3);
- }
-
- strcpy(path, &mem_block[ppos]); /* copy our current "PATH=" string */
-
- if(!strcmp(argv[firstarg],"^")) /* Insert at head of path */
- sprintf(cmdpath,"%s%s%s", target, argv[firstarg+1],
- path+strlen(target));
- else if (!strcmp(argv[firstarg], "$")) /* Append to tail of path */
- sprintf(cmdpath, "%s%s",path,argv[firstarg+1]);
- else /* Substitute into path */
- {
- strcpy(cmdpath,path);
- i = strsub(cmdpath+strlen(target), argv[firstarg],
- argv[firstarg+1], 1);
- if(i == 0)
- {
- target[strlen(target)-1] = NULL;
- fprintf(stderr,
- "PATHSUB: pattern [%s] not found in environment variable [%s].\n",
- argv[firstarg], target);
- exit(2);
- }
- }
-
- /* Remove old entry FROM OUR COPY of environment block */
- delete(mem_block, ppos);
-
- /* Make new entry in OUR COPY of environment block. If the addition */
- /* fits, THEN copy entire block back where it came from */
- if(append(mem_block, cmdpath, ctrl_block.length*16))
- {
- movedata(ds, (unsigned)mem_block, _mem_seg, 0, ctrl_block.length*16);
- exit(0);
- }
-
- /* if it did not get successfully added, just leave */
- fprintf(stderr,
- "PATHSUB: Not enough environment space -- environment unchanged\n");
- exit(1);
- }
-
- /* ===================== String handling routines ========================= */
- /* Purpose: this routine will substitute up to "num" occurances of the *
- * pattern "pat" in the string "s" with the replacement "sub". *
- * the actual number of substitutions performed is returned. *
- * if "num" is -1, then all occurances of "pat" are changed. *
- */
- int strsub(s, pat, sub, num)
- char *s, *pat, *sub;
- int num;
- {
- int idx, i, ii, count, off;
- char news[161];
-
- for( count = off = 0; TRUE; count++)
- {
- /* we only need to check string past end of last substitution */
- idx = stridx(&s[off], pat);
- /* if count is over the limit and limit specified,
- or pattern not found */
- if( ((count >= num) && (num != -1)) || (idx == -1))
- return count+1;
-
- /* idx + off is now the offset to the beginning of pat in s */
- /* copy from up to pattern in string to local buffer */
- for (i = off; i < idx+off; i++) /* only need to cp from last chg */
- news[i] = s[i];
-
- /* ad the substitution */
- for (ii = 0; ii < strlen(sub); ii++)
- news[i+ii] = sub[ii];
-
- /* finish copying the rest of the string */
- ii = idx+off + strlen(sub); /* where src picks up */
- i = idx+off + strlen(pat); /* where need end on dest */
- off = ii; /* remember for next cycle */
- while(s[i])
- news[ii++] = s[i++];
- news[ii] = NULL;
- strcpy(s, news);
- }
- return count; /* return number of subs done */
- }
-
-
- int stridx(s,p)
- char *s,*p;
- {
- char *p2;
-
- if( p2 = strstr(s,p)) /* if p found in s, */
- return p2-s; /* return offset into s */
- return -1; /* else return -1 */
- }
-
-
- unsigned _showds()
- {
- struct SREGS segregs;
-
- segread(&segregs); /* read the segment registers */
- return(segregs.ds); /* return DS */
- }
-
- int memsrch(mem,str,len)
- char *mem, *str;
- int len;
- {
- int i, j;
-
- len -= strlen(str);
- /* for each character of mem */
- for( j = 0; j <= len; j++)
- {
- /* compare the following chars */
- for( i = 0 ; (mem[j+i] == str[i]) && str[i]; i++);
- if(!str[i]) /* if at end of string */
- return j; /* return the index */
- }
- return -1;
- }
-
- delete(block, index)
- char *block;
- int index;
- {
- int size, end;
-
- /* find end of environment (2nd of 2 NULLs in a row) */
- for( end = 1; block[end-1] || block[end]; end++);
-
- /* get length of entry being deleted */
- size = strlen(&block[index])+1;
-
- /* shift the remaining block down on top of string being deleted */
- for(index += size; index <= end; index++)
- block[index-size] = block[index];
- }
-
- append(block, string, maxlen)
- char *block, *string;
- unsigned int maxlen;
- {
- int end, size, i;
-
- /* find starting point for string to be added */
- for( end = 1; block[end-1] || block[end]; end++);
-
- size = strlen(string) + 2; /* measure length of new string + 2 NULLs */
-
- /* check to see where last (proposed) byte falls in block */
- if((end+size) > maxlen)
- return(FALSE);
- /* copy it -- we have enough room */
- for( i = 0; string[i]; block[end++] = string[i++]);
- block[end++] = NULL;
- block[end++] = NULL;
-
- return TRUE;
- }
-